#pragma once

#include <iomanip>
#include <iostream>

namespace csz {
	/* 数组工具类 */
	template<class T>
	class Array {
	private:
		int size;
		T* arrPtr;
		/* 构造方法设为私有，只能通过静态方法获取实例对象*/
		Array() {
			this->size = 0;
			this->arrPtr = NULL;
		}
	public:
		Array(Array<T>* array) {
			Array<T>* arrayDup = array->copy();
			this->arrPtr = arrayDup->arrPtr;
			this->size = arrayDup->size;
		}
		Array(T array[], int size) {
			this->arrPtr = array;
			this->size = size;
		}
		~Array() {
			free(arrPtr);
		}
		T* getArray() {
			return this->arrPtr;
		}
		int getSize() {
			return this->size;
		}
		/* 生成固定长度数组，返回指向该数组的指针*/
		static Array<T>* GetRandArr(int size, int maxValue) {
			srand((unsigned int)time(0));
			if (size <= 0 || maxValue <= 0) {
				throw std::invalid_argument("参数错误");
			}
			T* arr = (T*)malloc(sizeof(T) * size);
			if (arr == NULL) {
				throw "内存申请异常！";
			}
			for (int i = 0; i < size; i++) {
				*(arr + i) = rand() % maxValue + 1;
			}
			Array<T>* arrObj = new Array<T>();
			arrObj->size = size;
			arrObj->arrPtr = arr;
			return arrObj;
		}

		/* 生成随机长度数组,参数为闭区间，返回指向该数组的指针*/
		static Array<T>* GetRandArr(int minSize, int maxSize, int maxValue) {
			srand((unsigned int)time(0));
			if (minSize <= 0 || maxSize <= 0 || minSize > maxSize || maxValue <= 0) {
				throw std::invalid_argument("参数错误！");
			}
			int tmpSize = minSize == maxSize ? minSize : rand() % (maxSize - minSize) + minSize;
			Array<T>* arrObj = Array<T>::GetRandArr(tmpSize, maxValue);
			return arrObj;
		}
		/* 打印数组数据 */
		void print() {
			Array<T>::Print(this->arrPtr, this->size);
		}
		/* 打印数组数据 */
		static void Print(T* arr, int len) {
			std::cout.setf(std::ios::left);
			for (int i = 0; i < len; i++) {
				std::cout << std::setw(3) << arr[i];
				if (i != len - 1) {
					std::cout << ",";
				}
				else {
					std::cout << std::endl;
				}
			}
		}

		/* 复制数组，该方法不是简单的复制引用，而是申请了一个全新的内存对象*/
		Array<T>* copy() {
			Array<T>* arrObj = new Array<T>();
			arrObj->size = this->size;
			arrObj->arrPtr = Array<T>::Copy(this->arrPtr, this->size);
			return arrObj;
		}
		/* 复制数组，该方法不是简单的返回引用，而是申请了一个全新的内存对象*/
		static T* Copy(T* src, int size) {
			T* dest = (T*)malloc(sizeof(T) * size);
			if (src == NULL || dest == NULL || size <= 0) {
				throw "参数错误!";
			}
			for (int i = 0; i < size; i++) {
				dest[i] = src[i];
			}
			return dest;
		}
		/* 将源数组中的数据复制到目标数组中*/
		static void Copy(T* dest, int destFrom, T* src, int srcFrom, int size) {
			if (dest == NULL || src == NULL || size <= 0 || destFrom < 0 || srcFrom < 0){
				throw "数组复制参数错误!";
			}
			for (int i = 0; i < size; i++) {
				dest[destFrom + i] = src[srcFrom + i];
			}
		}

		/* 判断数组是否相等，此方法会逐一比较数组中每一个元素值，若数组长度不等，也返回false*/
		bool equal(Array<T>* array) {
			return this->size == array->size && Array<T>::IsEqual(this->arrPtr, array->arrPtr, this->size);
		}
		/* 判断数组是否相等*/
		static bool IsEqual(T a[], T b[], int size) {
			int i = size;
			while (i-- > 0) {
				if (a[i] != b[i]) {
					return false;
				}
			}
			return true;
		}

		/* 交换两个数字*/
		static void Swap(T* a, T* b) {
			int tmp;
			tmp = *a;
			*a = *b;
			*b = tmp;
		}

		/* 合并Array对象，返回新的本对象*/
		void merge(Array<T>* array) {
			if (array == NULL || array->size <= 0 || array->arrPtr == NULL) {
				return;
			}
			T* newArr = (T*)malloc(sizeof(T) * (this->size + array->size));
			if (newArr == NULL) {
				throw "合并数组时申请空间失败";
			}
			Array<T>::Copy(newArr, 0, this->arrPtr, 0, this->size);
			Array<T>::Copy(newArr, this->size, array->arrPtr, 0, array->size);
			this->size = this->size + array->size;
			this->arrPtr = newArr;
		}

		/* 数组洗牌算法*/
		static void shuffle(T* array, int size) {
			srand((unsigned int)time(0));
			for (int i = size-1; i > 0; i--) {
				Array<T>::Swap(array + i, array + rand()%i);
			}
		}
		/* 数组洗牌算法*/
		void shuffle() {
			Array<T>::shuffle(this->arrPtr, this->size);
		}
	};
}